import java.util.*;

/**
 * Created by natalia on 10/1/14.
 */
public class Hand {
	private ArrayList<Card> cards = new ArrayList<Card>();
	private String name;

	Hand(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public ArrayList<Card> getHandCards() {
        return this.cards;
    }

	public void addCard(Card card) {
		cards.add(card);
	}

	public void printCards() {
		for(Card card: cards) {
			System.out.println("Card colour " + card.getColour() + "\t");
			System.out.println("Card level " + card.getLevel() + "\t");
			System.out.println("Card suit " + card.getSuit() + "\n");
		}
	}

    public Combination getCombination() {
        return Game.findCombination(this);
    }

    public static Combination isStraight(List<Card> cards) {
        int count = 1;
        Card currentCard = cards.get(0);
        Card first = cards.get(0);
        int i = 1;

        while(i < cards.size()) {
            if(cards.get(i) == currentCard) {
                i++;
                continue;
            }
            if(currentCard.getLevel().getValue() - cards.get(i).getLevel().getValue() == 1) {
                currentCard = cards.get(i);
                count++;
            } else {
                first = cards.get(i);
                count = 1;
                currentCard = cards.get(i);
            }
            if(count == 5) {
                if(i == cards.size() - 1 || cards.get(i).getLevel().getValue() - cards.get(i+1).getLevel().getValue() > 1) {
                    return new Combination(Combination.LEVELS.STRAIGHT, first);
                } else {
                    count = 1;
                    while(i < cards.size() - 1 && cards.get(i).getLevel().getValue() - cards.get(i+1).getLevel().getValue() <= 1) {
                        i++;
                        if(i == cards.size()) {
                            return null;
                        }
                        currentCard = cards.get(i);
                        first = cards.get(i);
                    }
                }
            }
            i++;
        }

        return null;
    }

    public static Combination checkIfFlush(List<Card> cards) {
        Card.SUIT suit = cards.get(0).getSuit();

        for(Card card: cards) {
            if(suit != card.getSuit() ) {
                return null;
            }
        }
        return new Combination(Combination.LEVELS.FLUSH, cards.get(0));
    }

    public static Combination isFourOfALevel(List<Card> cards) {
        Card firstCard = cards.get(0);
        int count = 1;
        int i = 0;

        if(firstCard.getLevel() != cards.get(1).getLevel()) {
            firstCard = cards.get(1);
            i = 1;
        }
        for( ; i < cards.size(); i++ ) {
            if(firstCard.getLevel() == cards.get(i).getLevel()) {
                count ++;
            }
        }
        if(count == 5) {
            return new Combination(Combination.LEVELS.FOUR_KINDS, cards.get(1));
        }
        return null;
    }



    public static Combination pairs(List<Card> cards) {
        class CardCounter {
            private int counter;
            private final Card card;

            CardCounter(int counter, Card card) {
                this.counter = counter;
                this.card = card;
            }
            public int getCounter() {
                return counter;
            }

            public Card getCard() {
                return card;
            }
            public void incrCounter() {
                this.counter ++;
            }

        }

        Map<Card.LEVELS, CardCounter> handCards = new HashMap<Card.LEVELS, CardCounter>();

        for(Card card: cards) {
            CardCounter cardCounter = handCards.get(card.getLevel());
            if(cardCounter == null) {
                handCards.put(card.getLevel(), new CardCounter(1, card));
            } else {
                cardCounter.incrCounter();
            }
        }


		List<CardCounter> forTwo = new ArrayList<CardCounter>();
		List<CardCounter> forThree = new ArrayList<CardCounter>();

		for(Card.LEVELS level: handCards.keySet()) {
			if(handCards.get(level).getCounter() == 2 ) {
				forTwo.add(handCards.get(level));
			} else if(handCards.get(level).getCounter() == 3) {
				forThree.add(handCards.get(level));
			}
		}
		if(forTwo.size() == 1 && forThree.size() == 1) {
			return new Combination(Combination.LEVELS.FULL_HOUSE, forThree.get(0).getCard());
		} else if(forThree.size() == 1 ) {
			return new Combination(Combination.LEVELS.THREE_KINDS, forThree.get(0).getCard());
		} else if(forTwo.size() == 2) {
			return new Combination(Combination.LEVELS.PAIRS, forTwo.get(0).getCard());
		} else if(forTwo.size() == 1) {
			return new Combination(Combination.LEVELS.PAIR, forTwo.get(0).getCard());
		}
        return null;
    }

	public static Combination isStraightFlush(List<Card> cards) {
		Combination combination = Hand.isStraight(cards);

		if(combination != null && combination.getLevelOfCard() == Combination.LEVELS.STRAIGHT) {
			combination = Hand.checkIfFlush(cards);
			if(combination != null && combination.getLevelOfCard() == Combination.LEVELS.FLUSH) {
				return new Combination(Combination.LEVELS.STRAIGHT_FLUSH, combination.getRankCard());
			}
		}

		return null;
	}

	public static Combination isRoyalFlush(List<Card> cards) {
		Combination combination = Hand.isStraightFlush(cards);

		if(combination != null && combination.getRankCard().getLevel() == Card.LEVELS.TOUZ) {
			return new Combination(Combination.LEVELS.ROYAL_FLUSH, combination.getRankCard());
		}
		return null;
	}
}
